function reloader(dom){
	if(dom==null||dom==undefined||dom==""){
		templateInit(document);
	}else if(dom.getElementsByClassName("mloader-template").length>0){
		templateInit(dom);
	}else{
		templateLoader(dom);
	}
}

new domFunction(function() {
	templateInit(document);
}, {
	'mloader-template': 'class'
});

//存储添加元素，以便判断是否重复
var elementStack = new Array();

//这里的写法还需要研究，为什么把clasz写在函数里面会执行出错？
var clasz=null;
function templateInit(dom) {
	if(clasz==null){
	 	clasz = dom.getElementsByClassName("mloader-template");
	}
	for(var i = 0; i < clasz.length; i++) {
		//console.log(dom.nodeName+"---"+clasz.length);
		var template = clasz[i];
		templateLoader(template);
	}
}

function templateLoader(template) {
	var ajax;
	try {
		ajax = new XMLHttpRequest();
	} catch(e) {
		alert(e);
	}
	ajax.open("get", template.getAttribute("url"), false);//同步请求
	ajax.setRequestHeader("Content-Type", "text/html;charset=utf-8");
	ajax.onreadystatechange = function() {
		if(ajax.readyState == 4) {
			if(ajax.status == 200) {
				var htmlText = ajax.responseText;
				//先去掉注释
				htmlText=filterNotes(htmlText);
				//传值赋值
				htmlText = analysisData(htmlText, template);
				//处理js与css外部文件引入
				htmlText = analysisJs(htmlText);
				htmlText = analysisCss(htmlText);
				//模板赋值
				template.innerHTML = htmlText;
				//移除已处理的标签
				removeClazz(template,"mloader-template");
				//加入新的已处理标签
				addClazz(template,"mloader-template-complete");
				//处理内部js代码，即<script></script>标签中的js
				htmlText = analysisJsScript(htmlText,template);
				//遍历template是否包含template
				templateInit(template);
			}
		}
	}
	ajax.send(null);
}

function removeClazz(ele,txt){
	var str =  ele.className,
        index = str.indexOf(txt);
    if(index > -1){
        ele.className = str.replace(txt,"");
    }
}

function addClazz(ele,txt){
    ele.className += txt;
}

/**
 * 去掉注释
 * @param {Object} htmlText
 */
function filterNotes(htmlText){
	if(htmlText.indexOf("<!--")!=-1){
		var noteTemp=htmlText.substring(htmlText.indexOf("<!--"));
		var note=noteTemp.substring(0,noteTemp.indexOf("-->")+3);
		htmlText=htmlText.replace(note,"");
		return filterNotes(htmlText);
	}
	return htmlText;
}

function analysisIf(htmlText, jsonData) {
	var domTag = new DOMParser().parseFromString(htmlText, "text/html");
	//初始化if，所有的全部先隐藏
	var ifTags = domTag.querySelectorAll("[m-if]");
	var elifTags = domTag.querySelectorAll("[m-elif]");
	var elseTags = domTag.querySelectorAll("[m-else]");
	if(ifTags != null) {
		ifTags.forEach(function(item) {
			item.style.display = "none";
		});
	}
	if(elifTags != null) {
		elifTags.forEach(function(item) {
			item.style.display = "none";
		});
	}
	if(elseTags != null) {
		elseTags.forEach(function(item) {
			item.style.display = "none";
		});
	}
	//处理m-if
	if(ifTags != null) {
		//处理非for循环下的if中有嵌套语句的问题
		//处理if中嵌套语句
		ifTags.forEach(function(item){
			if(item.getAttribute("m-if").includes("||") 
			|| item.getAttribute("m-if").includes("&amp;&amp;")
			||item.getAttribute("m-if").includes("&&") 
			||item.getAttribute("m-if").includes("!")
			||item.getAttribute("m-if").includes("!=")
			||item.getAttribute("m-if").includes("==")
			||item.getAttribute("m-if").includes("===")){//包含语句就处理
				var itemKey=item.getAttribute("m-if");
				itemKey=itemKey.replace(/\{|}/g,"");
				var mItemKey = itemKey;
				itemKey=itemKey.replace(/!(?!=)/g,"");
				var itemKeyList = itemKey.split(/\|\||&amp;&amp;|&&|!=|==|===/);
				for(var j = 0; j < itemKeyList.length; j++) {
					if(itemKeyList[j]==""||itemKeyList[j]=="null"||itemKeyList[j]=="undefined"||!jsonData.hasOwnProperty(itemKeyList[j])){
						continue;
					}
					
					var targetData=jsonData[itemKeyList[j]];
					
					if(targetData!=true
						&&targetData!="true"
						&&targetData!=false
						&&targetData!="false"
						&&targetData!=null
						&&targetData!="null"
						&&targetData!=""){
						mItemKey = mItemKey.replace(itemKeyList[j], "'"+targetData+"'");
					}else{
						mItemKey = mItemKey.replace(itemKeyList[j], targetData);
					}
				}
				mItemKey = mItemKey.replace("&amp;&amp;", "&&");
				var val=eval(mItemKey);
				item.setAttribute("m-if",val);
			}
		});
		//处理else if中嵌套语句
		elifTags.forEach(function(item){
			if(item.getAttribute("m-elif").includes("||") 
			|| item.getAttribute("m-elif").includes("&amp;&amp;")
			||item.getAttribute("m-elif").includes("&&")
			||item.getAttribute("m-elif").includes("!")
			||item.getAttribute("m-elif").includes("!=")
			||item.getAttribute("m-elif").includes("==")
			||item.getAttribute("m-elif").includes("===")){//包含语句就处理
				var itemKey=item.getAttribute("m-elif");
				itemKey=itemKey.replace(/\{|}/g,"");
				var mItemKey = itemKey;
				itemKey=itemKey.replace(/!(?!=)/g,"");
				var itemKeyList = itemKey.split(/\|\||&amp;&amp;|&&|!=|==|===/);
				for(var j = 0; j < itemKeyList.length; j++) {
					if(itemKeyList[j]==""||itemKeyList[j]=="null"||itemKeyList[j]=="undefined"||!jsonData.hasOwnProperty(itemKeyList[j])){
						continue;
					}
					
					var targetData=jsonData[itemKeyList[j]];
					
					if(targetData!=true
						&&targetData!="true"
						&&targetData!=false
						&&targetData!="false"
						&&targetData!=null
						&&targetData!="null"
						&&targetData!=""){
						mItemKey = mItemKey.replace(itemKeyList[j], "'"+targetData+"'");
					}else{
						mItemKey = mItemKey.replace(itemKeyList[j], targetData);
					}
				}
				mItemKey = mItemKey.replace("&amp;&amp;", "&&");
				var val=eval(mItemKey);
				item.setAttribute("m-elif",val);
			}
		});
		ifTags.forEach(function(item) {
			//处理已经在for循环里面赋值后的结果，即处理for嵌套if的情况
			if(item.getAttribute("m-if") == "false") {
				var nextNode = item.nextElementSibling;
				var elifTagFlag = null;
				while(nextNode != null && nextNode.hasAttribute("m-elif")) {
					if(nextNode.getAttribute("m-elif") == "false") {
						nextNode.style.display = "none";
						nextNode = nextNode.nextElementSibling;
					} else {
						nextNode.style.display = "block";
						elifTagFlag = true;
						break;
					}
				}
				if(nextNode != null && nextNode.hasAttribute("m-else") && (elifTagFlag == null || (elifTagFlag != null && !elifTagFlag))) {
					nextNode.style.display = "block";
				}
			} else if(item.getAttribute("m-if") == "true") {
				item.style.display = "block";
			} else { //这里是未嵌套时处理的情况
				//处理if的数据
				var ifTagFlag = null;
				var elifTagFlag = null;
				var nextNode = null;
				for(var key in jsonData) {
					if(item.getAttribute("m-if") == key) {
						if(jsonData[key]) {
							item.style.display = "block";
							ifTagFlag = true;
							break;
						} else {
							item.style.display = "none";
							ifTagFlag = false;
							nextNode = item.nextElementSibling;
						}
					}
					//处理m-elif或者m-else
					if(ifTagFlag != null && !ifTagFlag) {
						//判断if后面有没有elif标签
						//处理elif
						while(nextNode != null && nextNode.hasAttribute("m-elif") && (elifTagFlag == null || (elifTagFlag != null && !elifTagFlag)) && nextNode.getAttribute("m-elif") == key) {
							if(jsonData[key]) {
								nextNode.style.display = "block";
								elifTagFlag = true;
								break;
							} else {
								nextNode.style.display = "none";
								nextNode = nextNode.nextElementSibling;
							}
						}
						//处理else
						if(nextNode != null && nextNode.hasAttribute("m-else") && (elifTagFlag == null || (elifTagFlag != null && !elifTagFlag))) {
							nextNode.style.display = "block";
						}
					}
				}
			}
		});
	}
	htmlText = domTag.body.innerHTML;
	return htmlText;
}

function analysisFor(htmlText, jsonData) {
	var domTag = new DOMParser().parseFromString(htmlText, "text/html");
	var forTags = domTag.querySelectorAll("[m-for]");
	if(forTags.length > 0) {
		for(var key in jsonData) {
			forTags.forEach(function(item) {
				if(item.getAttribute("m-for") == key) {
					var list = jsonData[key];
					var strModel = item.innerHTML;
					var strAll = "";
					for(var i = 0; i < list.length; i++) {
						var strTemp = strModel;
						var sIndex = new RegExp("{index}", "g");
						strTemp = strTemp.replace(sIndex, i);

						strTemp = analysisItemKey(strTemp, list[i]);

						strAll += strTemp;
					}
					item.innerHTML = strAll;
				}
			});
		}
		htmlText = domTag.body.innerHTML;
	}
	return htmlText;
}

/**
 * for循环中取值递归
 */
function analysisItemKey(strTemp, item) {
	if(strTemp.indexOf("{item") != -1) {
		var itemKeyTemp = strTemp.substring(strTemp.indexOf("{item"));
		var itemKey = itemKeyTemp.substring(1, itemKeyTemp.indexOf("}"));
		if(itemKey.includes("||") || itemKey.includes("&amp;&amp;")|| itemKey.includes("&&")||itemKey.includes("!")||itemKey.includes("!=")||itemKey.includes("==")||itemKey.includes("===")) { //包含语句
			itemKey=itemKey.replace(/\{|}/g,"");
			var mItemKey = itemKey;
			itemKey=itemKey.replace(/!(?!=)/g,"");
			var itemKeyList = itemKey.split(/\|\||&amp;&amp;|&&|!=|==|===/);
			for(var j = 0; j < itemKeyList.length; j++) {
				if(itemKeyList[j]==""||itemKeyList[j]=="null"||itemKeyList[j]=="undefined"||(itemKeyList[j].indexOf(".")==-1&&!item.hasOwnProperty(itemKeyList[j]))){
					continue;
				}
				var itemKeyArr = itemKeyList[j].split(".");
				var itemValue = item;
				for(var i = 0; i < itemKeyArr.length; i++) {
					if(i > 0) {
						itemValue = itemValue[itemKeyArr[i]];
					}
				}
				if(itemValue!=true
					&&itemValue!="true"
					&&itemValue!=false
					&&itemValue!="false"
					&&itemValue!=null
					&&itemValue!="null"
					&&itemValue!=""){
					mItemKey = mItemKey.replace(itemKeyList[j], "'"+itemValue+"'");
				}else{
					mItemKey = mItemKey.replace(itemKeyList[j], itemValue);
				}
			}
			mItemKey = mItemKey.replace(/&amp;&amp;/g, "&&");
			var reg=itemKey.replace(/\|/g,"\\|");
			var sItemKey = new RegExp("{" + reg + "}", "g");
			var val=eval(mItemKey)
			strTemp = strTemp.replace(sItemKey, val);
			return analysisItemKey(strTemp, item);
		} else { //不包含语句
			var itemKeyArr = itemKey.split(".");
			var itemValue = item;
			for(var i = 0; i < itemKeyArr.length; i++) {
				if(i > 0) {
					itemValue = itemValue[itemKeyArr[i]];
				}
			}
			var sItemKey = new RegExp("{" + itemKey + "}", "g");
			strTemp = strTemp.replace(sItemKey, itemValue);
			return analysisItemKey(strTemp, item);
		}
	}
	return strTemp;
}

function analysisWords(htmlText, jsonData) {
	for(var key in jsonData) {
		//处理字段值
		//if(!isNumber(key)) {
		var str = new RegExp("{" + key + "}", "g");
		var data=jsonData[key];
		//修复空值导致代码报错的问题
		if(data==""){
			data=null;
		}
		htmlText = htmlText.replace(str, data)
		//}
	}
	return htmlText;
}

function isNumber(val) {
	var regPos = /^\d+(\.\d+)?$/; //非负浮点数
	var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
	if(regPos.test(val) || regNeg.test(val)) {
		return true;
	} else {
		return false;
	}
}

/**
 * 处理data传值
 */
function analysisData(htmlText, template) {
	var dataName = template.getAttribute("data");
	if(dataName != null) {
		var jsonData = window[dataName];
		if(Array.isArray(jsonData)) {
			jsonData = {
				[dataName]: jsonData
			};
		}
		htmlText = analysisFor(htmlText, jsonData);
		htmlText = analysisIf(htmlText, jsonData);
		htmlText = analysisWords(htmlText, jsonData);
	}
	return htmlText;
}

/**
 * 1.查找下一个import-js标签
 * 2.获取标签内容
 * 3.获取标签src内容
 * 4.给html后追加js内容
 * 5.删除htmlText中的该循环中获取的标签
 * 6.重复以上步骤，直到所有的import-js标签已全部处理完成
 */
function analysisJs(htmlText) {
	if(htmlText.indexOf("<import-js") != -1) {
		var jsTagTemp = htmlText.substring(htmlText.indexOf("<import-js"));
		var jsTag = jsTagTemp.substring(0, jsTagTemp.indexOf(">") + 1);
		var jsSrcTemp = jsTag.substring(jsTag.indexOf("\"") + 1);
		var jsSrc = jsSrcTemp.substring(0, jsSrcTemp.indexOf("\""));
		//给html标签追加js内容
		if(jsSrc != null && jsSrc != "") {
			var htmlTag = document.getElementsByTagName("html")[0];
			var jsElement = document.createElement("script");
			jsElement.src = jsSrc;
			jsElement.type = "text/javascript";
			jsElement.charset = "UTF-8";
			//判断是否重复添加
			if(elementStack.indexOf(jsSrc) == -1) {
				htmlTag.appendChild(jsElement);
				elementStack.push(jsSrc);
			}
		}
		//删除htmlText中的该循环中获取的标签
		htmlText = htmlText.replace(jsTag, "");
		//递归循环
		return analysisJs(htmlText);
	}
	return htmlText;

}

/**
 * css和js处理原理差不多
 */
function analysisCss(htmlText) {
	if(htmlText.indexOf("<import-css") != -1) {
		var cssTagTemp = htmlText.substring(htmlText.indexOf("<import-css"));
		var cssTag = cssTagTemp.substring(0, cssTagTemp.indexOf(">") + 1);
		var cssSrcTemp = cssTag.substring(cssTag.indexOf("\"") + 1);
		var cssSrc = cssSrcTemp.substring(0, cssSrcTemp.indexOf("\""));
		//给head标签追加js内容
		if(cssSrc != null && cssSrc != "") {
			var headTag = document.getElementsByTagName("head")[0];
			var cssElement = document.createElement("link");
			cssElement.href = cssSrc;
			cssElement.rel = "stylesheet";
			cssElement.type = "text/css";
			//判断是否重复添加
			if(elementStack.indexOf(cssSrc) == -1) {
				headTag.appendChild(cssElement);
				elementStack.push(cssSrc);
			}
		}
		//删除htmlText中的该循环中获取的标签
		htmlText = htmlText.replace(cssTag, "");
		//递归循环
		return analysisCss(htmlText);
	}
	return htmlText;

}

/**
 * 和js和css大同小异
 */
function analysisJsScript(htmlText,template) {
	if(htmlText.indexOf("<script") != -1) {
		var scriptTagTemp = htmlText.substring(htmlText.indexOf("<script"));
		var scriptTag = scriptTagTemp.substring(0, scriptTagTemp.indexOf("</script>") + 9);
		//转成node好去掉script标签
		var domScriptTag = new DOMParser().parseFromString(scriptTag, "text/html").head.childNodes[0];
		var htmlTag = document.getElementsByTagName("html")[0];
		var jsElement = document.createElement("script");
		jsElement.innerHTML = domScriptTag.innerHTML;
		//判断是否重复添加
		if(elementStack.indexOf(domScriptTag.innerHTML) == -1) {
			htmlTag.appendChild(jsElement);
			elementStack.push(domScriptTag.innerHTML);
		}else{
			for(var i=0;i<htmlTag.childNodes.length;i++){
				if(htmlTag.childNodes[i].isEqualNode(jsElement)){
					htmlTag.removeChild(htmlTag.childNodes[i]);
					htmlTag.appendChild(jsElement);
				}
			}
		}
		for(var i=0;i<template.childNodes.length;i++){
			if(template.childNodes[i].isEqualNode(jsElement)){
				template.removeChild(template.childNodes[i]);
			}
		}
		//删除htmlText中的该循环中获取的标签
		htmlText = htmlText.replace(scriptTag, "");
		//递归循环
		return analysisJsScript(htmlText,template);
	}
	return htmlText;
}

function setValue(key,value){
	localStorage.setItem(key,value);
}

function getValue(key){
	localStorage.getItem(key);
}
var callback;
function setCallback(c){
	callback=c;
}

function getCallback(){
	return callback;
}

// DF1.1 :: domFunction
// *****************************************************
// DOM scripting by brothercake -- http://www.brothercake.com/
// GNU Lesser General Public License -- http://www.gnu.org/licenses/lgpl.html
//******************************************************

//DOM-ready watcher
function domFunction(f, a) {
	//initialise the counter
	var n = 0;
	//start the timer
	var t = setInterval(function() {
		//continue flag indicates whether to continue to the next iteration
		//assume that we are going unless specified otherwise
		var c = true;
		//increase the counter
		n++;
		//if DOM methods are supported, and the body element exists
		//(using a double-check including document.body, for the benefit of older moz builds [eg ns7.1]
		//in which getElementsByTagName('body')[0] is undefined, unless this script is in the body section)
		if(typeof document.getElementsByTagName != 'undefined' && (document.getElementsByTagName('body')[0] != null || document.body != null)) {
			//set the continue flag to false
			//because other things being equal, we're not going to continue
			c = false;
			//but ... if the arguments object is there
			if(typeof a == 'object') {
				//iterate through the object
				for(var i in a) {
					//if its value is "id" and the element with the given ID doesn't exist
					//or its value is "tag" and the specified collection has no members
					if(
						(a[i] == 'id' && document.getElementById(i) == null) ||
						(a[i] == 'class' && document.getElementsByClassName(i).length < 1) ||
						(a[i] == 'tag' && document.getElementsByTagName(i).length < 1)
					) {
						//set the continue flag back to true
						//because a specific element or collection doesn't exist
						c = true;
						//no need to finish this loop
						break;
					}
				}
			}
			//if we're not continuing
			//we can call the argument function and clear the timer
			if(!c) {
				f();
				clearInterval(t);
			}
		}
		//if the timer has reached 60 (so timeout after 15 seconds)
		//in practise, I've never seen this take longer than 7 iterations [in kde 3
		//in second place was IE6, which takes 2 or 3 iterations roughly 5% of the time]
		if(n >= 100) {
			//clear the timer
			clearInterval(t);
		}
	}, 10);
};